﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SocialKit.LightRest;

namespace SocialKit.QQPengyou
{
    /// <summary>
    /// 表示腾讯社区开放平台API客户端。
    /// </summary>
    public class PengyouApiClient
    {
        /// <summary>
        /// 表示API基地址字符串（http://openapi.pengyou.qq.com）。
        /// </summary>
        public const string API_HOST = "http://openapi.pengyou.qq.com";


        #region REST CLIENT

        RestClient proxy;

        /// <summary>
        /// 表示REST客户端。
        /// </summary>
        protected virtual RestClient RestApiClient
        {
            get
            {
                if (proxy == null)
                {
                    proxy = new RestClient(API_HOST);
                }

                return proxy;
            }
        }

        #endregion


        /// <summary>
        /// 获取应用的AppID。
        /// </summary>
        public long AppId { get; private set; }

        /// <summary>
        /// 获取应用的AppKey。
        /// </summary>
        public string AppKey { get; private set; }

        /// <summary>
        /// 获取应用的AppName。
        /// </summary>
        public string AppName { get; private set; }

        /// <summary>
        /// 获取从当前Http上下文中读取的OpenId字符串。
        /// </summary>
        public static string CurrentOpenId
        {
            get
            {
                if (HttpContext.Current == null)
                    return null;

                return HttpContext.Current.Request.QueryString.Get("openid");
            }
        }

        /// <summary>
        /// 获取从当前Http上下文中读取的OpenKey字符串。
        /// </summary>
        public static string CurrentOpenKey
        {
            get
            {
                if (HttpContext.Current == null)
                    return null;

                return HttpContext.Current.Request.QueryString.Get("openkey");
            }
        }


        /// <summary>
        /// 创建一个 SocialKit.QQPengyou.PengyouApiClient 的实例。
        /// </summary>
        /// <param name="appId">应用的AppID。</param>
        /// <param name="appKey">应用的AppKey。</param>
        /// <param name="appName">应用的AppName。</param>
        public PengyouApiClient(long appId, string appKey, string appName)
        {
            if (appId <= 0L)
                throw new ArgumentOutOfRangeException("appId");

            if (string.IsNullOrEmpty(appKey))
                throw new ArgumentNullException("appKey");

            if (string.IsNullOrEmpty(appName))
                throw new ArgumentNullException("appName");

            this.AppId = appId;
            this.AppKey = appKey;
            this.AppName = appName;
        }


        /// <summary>
        /// 判断OpenID是否符合规范。
        /// </summary>
        /// <param name="openId">OpenID字符串。</param>
        /// <returns></returns>
        static bool IsValidOpenId(string openId)
        {
            return Regex.IsMatch(openId, "^[0-9a-fA-F]{32}$");
        }


        #region API Methods

        /// <summary>
        /// 获取当前登录用户，包括用户基本资料以及黄钻级别等相关信息。
        /// </summary>
        /// <returns></returns>
        public Models.UserInfo GetUserInfo()
        {
            return GetUserInfo(CurrentOpenId, CurrentOpenKey);
        }

        /// <summary>
        /// 获取当前登录用户，包括用户基本资料以及黄钻级别等相关信息。
        /// </summary>
        /// <param name="openId">登录用户的OpenID。</param>
        /// <param name="openKey">登录用户的OpenKey。</param>
        /// <returns></returns>
        public Models.UserInfo GetUserInfo(string openId, string openKey)
        {
            var path = "/user/info";

            var query = new HttpQueryString()
                .Append("openid", openId)
                .Append("openkey", openKey)
                .Append("appid", this.AppId.ToString())
                .Append("appkey", this.AppKey)
                .Append("appname", this.AppName);

            return RestApiClient.Get(path, query).Ensure().ReadJsonContent<Models.UserInfo>();
        }

        /// <summary>
        /// 批量获取用户信息。
        /// </summary>
        /// <param name="fopenids">用户的OpenID列表。</param>
        /// <returns></returns>
        public IEnumerable<Models.UserInfo> GetUsers(params string[] fopenids)
        {
            return GetUsers(CurrentOpenId, CurrentOpenKey, fopenids);
        }

        /// <summary>
        /// 批量获取用户信息。
        /// </summary>
        /// <param name="openId">登录用户的OpenID。</param>
        /// <param name="openKey">登录用户的OpenKey。</param>
        /// <param name="fopenids">用户的OpenID列表。</param>
        /// <returns></returns>
        public IEnumerable<Models.UserInfo> GetUsers(string openId, string openKey, params string[] fopenids)
        {
            var path = "/user/multi_info";

            var query = new HttpQueryString()
                .Append("openid", openId)
                .Append("openkey", openKey)
                .Append("appid", this.AppId.ToString())
                .Append("appkey", this.AppKey)
                .Append("appname", this.AppName)
                .Append("fopenids", string.Join("_", fopenids));

            var json = RestApiClient.Get(path, query).Ensure().ReadJsonContent() as JObject;

            return JsonConvert.DeserializeObject<IEnumerable<Models.UserInfo>>(json["items"].ToString());
        }

        /// <summary>
        /// 验证登录用户是否安装了应用。已经安装返回true，否则返回false。
        /// </summary>
        /// <returns></returns>
        public bool IsSetuped()
        {
            return IsSetuped(CurrentOpenId, CurrentOpenKey);
        }

        /// <summary>
        /// 验证登录用户是否安装了应用。已经安装返回true，否则返回false。
        /// </summary>
        /// <param name="openId">登录用户的OpenID。</param>
        /// <param name="openKey">登录用户的OpenKey。</param>
        /// <returns></returns>
        public bool IsSetuped(string openId, string openKey)
        {
            var path = "/user/is_setuped";

            var query = new HttpQueryString()
                .Append("openid", openId)
                .Append("openkey", openKey)
                .Append("appid", this.AppId.ToString())
                .Append("appkey", this.AppKey)
                .Append("appname", this.AppName);

            var json = RestApiClient.Get(path, query).Ensure().ReadJsonContent() as JObject;

            return json["setuped"].ToString() == "1";
        }

        /// <summary>
        /// 批量获取用户的签名信息。
        /// </summary>
        /// <param name="fopenids">用户的OpenID列表。</param>
        /// <returns></returns>
        public IEnumerable<Models.EmotionInfo> GetEmotions(params string[] fopenids)
        {
            return GetEmotions(CurrentOpenId, CurrentOpenKey, fopenids);
        }

        /// <summary>
        /// 批量获取用户的签名信息。
        /// </summary>
        /// <param name="openId">登录用户的OpenID。</param>
        /// <param name="openKey">登录用户的OpenKey。</param>
        /// <param name="fopenids">用户的OpenID列表。</param>
        /// <returns></returns>
        public IEnumerable<Models.EmotionInfo> GetEmotions(string openId, string openKey, params string[] fopenids)
        {
            var path = "/user/emotion";

            var query = new HttpQueryString()
                .Append("openid", openId)
                .Append("openkey", openKey)
                .Append("appid", this.AppId.ToString())
                .Append("appkey", this.AppKey)
                .Append("appname", this.AppName)
                .Append("fopenids", string.Join("_", fopenids));

            var json = RestApiClient.Get(path, query).Ensure().ReadJsonContent() as JObject;

            return JsonConvert.DeserializeObject<IEnumerable<Models.EmotionInfo>>(json["items"].ToString());
        }

        /// <summary>
        /// 判断登录用户与指定OpenID的用户是否为好友关系，是好友返回true，否则返回false。
        /// </summary>
        /// <param name="fopenid">用户的OpenID。</param>
        /// <returns></returns>
        public bool IsFriend(string fopenid)
        {
            return IsFriend(CurrentOpenId, CurrentOpenKey, fopenid);
        }

        /// <summary>
        /// 判断登录用户与指定OpenID的用户是否为好友关系，是好友返回true，否则返回false。
        /// </summary>
        /// <param name="openId">登录用户的OpenID。</param>
        /// <param name="openKey">登录用户的OpenKey。</param>
        /// <param name="fopenid">用户的OpenID。</param>
        /// <returns></returns>
        public bool IsFriend(string openId, string openKey, string fopenid)
        {
            var path = "/relation/is_friend";

            var query = new HttpQueryString()
                .Append("openid", openId)
                .Append("openkey", openKey)
                .Append("appid", this.AppId.ToString())
                .Append("appkey", this.AppKey)
                .Append("appname", this.AppName)
                .Append("fopenid", fopenid);

            var json = RestApiClient.Get(path, query).Ensure().ReadJsonContent() as JObject;

            return int.Parse(json["isFriend"].ToString()) >= 1;
        }

        /// <summary>
        /// 获取好友关系链以及详细信息。
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Models.UserInfo> GetFriends()
        {
            return GetFriends(true, null, 0);
        }

        /// <summary>
        /// 获取好友关系链以及详细信息。
        /// </summary>
        /// <param name="openId">登录用户的OpenID。</param>
        /// <param name="openKey">登录用户的OpenKey。</param>
        /// <returns></returns>
        public IEnumerable<Models.UserInfo> GetFriends(string openId, string openKey)
        {
            return GetFriends(openId, openKey, true, null, 0);
        }

        /// <summary>
        /// 获取好友关系链以及详细信息。
        /// </summary>
        /// <param name="infoed">是否需要好友的详细信息。</param>
        /// <param name="apped">是否已经安装此应用。</param>
        /// <param name="page">页码（0表示不分页）。</param>
        /// <returns></returns>
        public IEnumerable<Models.UserInfo> GetFriends(bool infoed, bool? apped, int page)
        {
            return GetFriends(CurrentOpenId, CurrentOpenKey, infoed, apped, page);
        }

        /// <summary>
        /// 获取好友关系链以及详细信息。
        /// </summary>
        /// <param name="openId">登录用户的OpenID。</param>
        /// <param name="openKey">登录用户的OpenKey。</param>
        /// <param name="infoed">是否需要好友的详细信息。</param>
        /// <param name="apped">是否已经安装此应用。</param>
        /// <param name="page">页码（0表示不分页）。</param>
        /// <returns></returns>
        public IEnumerable<Models.UserInfo> GetFriends(string openId, string openKey, bool infoed, bool? apped, int page)
        {
            var path = "/relation/friends";

            var query = new HttpQueryString()
                .Append("openid", openId)
                .Append("openkey", openKey)
                .Append("appid", this.AppId.ToString())
                .Append("appkey", this.AppKey)
                .Append("appname", this.AppName)
                .Append("infoed", infoed ? "1" : "0")
                .Append("apped", apped.HasValue ? (apped.Value ? "1" : "-1") : "0")
                .Append("page", page.ToString());

            var json = RestApiClient.Get(path, query).Ensure().ReadJsonContent() as JObject;

            return JsonConvert.DeserializeObject<IEnumerable<Models.UserInfo>>(json["items"].ToString());
        }

        /// <summary>
        /// 判断当前登录用户是否是黄钻。
        /// </summary>
        /// <returns></returns>
        public bool IsVip()
        {
            return IsVip(CurrentOpenId, CurrentOpenKey);
        }

        /// <summary>
        /// 判断当前登录用户是否是黄钻。
        /// </summary>
        /// <param name="openId">登录用户的OpenID。</param>
        /// <param name="openKey">登录用户的OpenKey。</param>
        /// <returns></returns>
        public bool IsVip(string openId, string openKey)
        {
            var path = "/pay/is_vip";

            var query = new HttpQueryString()
                .Append("openid", openId)
                .Append("openkey", openKey)
                .Append("appid", this.AppId.ToString())
                .Append("appkey", this.AppKey)
                .Append("appname", this.AppName);

            var json = RestApiClient.Get(path, query).Ensure().ReadJsonContent() as JObject;

            return bool.Parse(json["is_vip"].ToString());
        }

        #endregion
    }
}